﻿using System;
using System.Collections.Generic;
using YawetagLib.Utilities;

namespace YawetagLib.Services
{
    public abstract class BaseServiceFactory : IServiceFactory
    {
        private readonly object _lock = new object();

        protected BaseServiceFactory()
        {
            Instances = new Dictionary<Type, IService>();
        }

        public IService Get(Type serviceType)
        {
            serviceType = TypeResolver.Get(serviceType);

            lock (_lock)
            {
                if (!Instances.ContainsKey(serviceType))
                {
                    Instances.Add(serviceType, GetServiceInstance(serviceType));
                }
            }

            return Instances[serviceType];
        }

        public TService Get<TService>() where TService : IService
        {
            return (TService)Get(typeof(TService));
        }

        protected virtual IService GetServiceInstance(Type serviceType)
        {
            return (IService)Activator.CreateInstance(serviceType);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!IsDisposed)
            {
                if (disposing)
                {
                    ManagedResourceCleanup();
                }
                UnmanagedResourceCleanup();
                IsDisposed = true;
            }
        }

        protected virtual void ManagedResourceCleanup()
        {
            foreach (IService service in Instances.Values)
            {
                service.Dispose();
            }
        }

        protected virtual void UnmanagedResourceCleanup()
        {
        }

        ~BaseServiceFactory()
        {
            Dispose(false);
        }

        private IDictionary<Type, IService> Instances { get; set; }

        private bool IsDisposed { get; set; }
    }
}
